#include "../logs/log.h"
/*扩展一个以时间作为入职文件滚动切换类型的日志落地模块
    1. 以时间进行文件滚动，实际上是以时间段进行滚动
        实现思想: 以当前系统时间，取模时间段大小，可以得到当前时间段时第几个时间段
            每次以当前系统时间取模，判断与当前文件的时间段是否一致，不一致代表不是同一个时间段
*/
enum class TimeGap
{
    GAP_SECOND =0,
    GAP_MINUTE,
    GAP_HOUR,
    GAP_DAY
};
class RollByTimeSink : public log::LogSink
{
   public:
        RollByTimeSink(const std::string& basename,TimeGap gap_type)
        :_basename(basename)
        { 
            switch(gap_type)
            {
                case TimeGap::GAP_SECOND: _gap_size =1;break;
                case TimeGap::GAP_MINUTE: _gap_size = 60;break;
                case TimeGap::GAP_HOUR: _gap_size =3600;break;
                case TimeGap::GAP_DAY: _gap_size = 3600 *24 ;break;
            }
            _cur_gap = log::util::Date::now() / _gap_size == 1? log::util::Date::now() : log::util::Date::now() / _gap_size;
            log::util::file::createDirectory(log::util::file::path(_basename));
            std::string filename = createNewFileName();
            _ofs.open(filename,std::ios::binary | std::ios::app);
            assert(_ofs.is_open());
        }
        void log(const char* data,size_t len) override
        {
            time_t cur = log::util::Date::now();
            if(cur /_gap_size != _cur_gap)
            {
                _ofs.close();
                std::string filename = createNewFileName();
                _ofs.open(filename,std::ios::binary | std::ios::app);
                assert(_ofs.is_open());
            }
            _ofs.write(data,len);
            assert(_ofs.good());
        }
        private:
        std::string createNewFileName()
        {
            //获取系统时间，以时间来构造文件名扩展名;
            std::stringstream ss;
            time_t t = log::util::Date::now();
            struct tm lt;
            localtime_r(&t,&lt);
            ss << _basename;
            ss << lt.tm_year+1900;
            ss << lt.tm_mon+1;
            ss << lt.tm_mday;
            ss << lt.tm_hour;
            ss << lt.tm_min;
            ss << lt.tm_sec;
            ss << ".log"; 

            return ss.str();
        }
        std::string _basename;
        std::ofstream _ofs;
        size_t _gap_size; //时间段大小
        size_t _cur_gap; //当前是第几个时间段
};
void test_1()
{
    log::LogMsg log1(log::LogLevel::value::INFO,
    log::util::Date::now(),
    53,
    "格式化功能测试",
    "root",
    "main.c");

    log::Formatter fmt("abc%%abc[%d{%H:%M:%S}] %m%n");
    std::string str = fmt.formate(log1);
    std::cout << str << std::endl;
}
void test_2()
{
    time_t t_old = log::util::Date::now();
    log::LogSink::ptr time_lsp = log::SinkFactory::Create<RollByTimeSink>("./logfile/roll-",TimeGap::GAP_SECOND);
    log::LogMsg msg(log::LogLevel::value::INFO,log::util::Date::now(),53,"格式化功能测试...","root","main.c");
    std::string str= log::Formatter().formate(msg);
    int i=0;
    while(log::util::Date::now()<t_old+5)
    {
        time_lsp->log(str.c_str(),str.size());
        usleep(1000);
    }
}
void test_3()
{
    log::LogSink::ptr time_lsp = log::SinkFactory::Create<RollByTimeSink>("./logfile/roll-",TimeGap::GAP_SECOND);
    //log::LogSink::ptr std_lsp = log::SinkFactory::Create<log::StdoutSink>();
    log::LogSink::ptr std_lsp = log::SinkFactory::Create<log::StdoutSink>();
    std::string logger_name("sync");
    log::Formatter::ptr fmt(new log::Formatter);
    std::vector<log::LogSink::ptr> sinks;
    sinks.push_back(time_lsp);
    sinks.push_back(std_lsp);
    time_t t_old = log::util::Date::now();
    log::Logger::ptr sync_logger(new log::SyncLogger(logger_name,log::LogLevel::value::DEBUG,fmt,sinks));
    while(log::util::Date::now()<t_old+5)
    {
        sync_logger->fatal(__FILE__,__LINE__,"%s","测试日志");
        usleep(1000);
    }
}
void test_4()
{
    std::shared_ptr<log::LoggerBuilder> builder(new log::LocalloggerBuilder());
    builder->buildFormatter("[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");
    builder->buildLoggerLevel(log::LogLevel::value::DEBUG);
    builder->buildLoggerName("sync");
    builder->buildLoggerType(log::Logger_type::LOGGER_SYNC);
    builder->buildSink<log::RollSinkBySize>("./logfile/rolls-",1024*1024 *100);
    builder->buildSink<RollByTimeSink>("./logfile/rollt-",TimeGap::GAP_SECOND);
    log::SyncLogger::ptr sync_logger  = builder->build();
    time_t t_old = log::util::Date::now();
    while(log::util::Date::now()<t_old+5)
    {
        sync_logger->fatal(__FILE__,__LINE__,"%s","测试日志");
    }
}
void test_5()
{
    std::ifstream ifs("./logfile/tmp.log",std::ios::binary);
    assert(ifs.is_open());
    ifs.seekg(0,std::ios::end);
    size_t len  = ifs.tellg();
    ifs.seekg(0,std::ios::beg);
    log::Buffer buffer;
    std::string body(len+1,0);
    ifs.read(&body[0],len);
    buffer.push(body.c_str(),body.size());
    std::ofstream ofs("./logfile/test.log",std::ios::binary | std::ios::app);
    assert(ofs.good());
    int i=0;
    int max = buffer.readablesize();
    for(;i<max;i++)
    {
        ofs.write(buffer.begin(),1);
        buffer.moveReader(1);
    }
    // std::cout << buffer.empty() <<" " <<i <<" " << buffer.readablesize()<< std::endl;
    ofs.close();
    ifs.close();
}
void test_log()
{
    log::Logger::ptr async_logger = log::LoggerManager::getInstance().getLogger("Async_logger");
    for(int i=0;i<50000;i++)
    {
        async_logger->debug("%s-%d-%s","测试信息",i+1,"test_log");
    } 
}
void test_6()
{
    std::shared_ptr<log::LoggerBuilder> builder(std::make_shared<log::GloballoggerBuilder>());
    builder->buildFormatter("[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");
    builder->buildLoggerLevel(log::LogLevel::value::DEBUG);
    builder->buildLoggerName("Async_logger");
    builder->buildLoggerType(log::Logger_type::LOGGER_ASYNC);
    //builder->buildSink<log::StdoutSink>();
    builder->buildEnableUnSafeAsync();
    builder->buildSink<log::FileSink>("./logfile/test.log");
    log::Logger::ptr async_logger = builder->build();

    for(int i=0;i<50000;i++)
    {
        async_logger->debug("%s-%d","测试信息",i+1);
    }   
}
int main()
{
    //test_2(); 
    std::shared_ptr<log::LoggerBuilder> builder(std::make_shared<log::GloballoggerBuilder>());
    builder->buildFormatter("[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");
    builder->buildLoggerLevel(log::LogLevel::value::DEBUG);
    builder->buildLoggerName("Async_logger");
    builder->buildLoggerType(log::Logger_type::LOGGER_ASYNC);
    builder->buildSink<log::StdoutSink>();
    builder->buildEnableUnSafeAsync();
    builder->buildSink<log::FileSink>("./logfile/test.log");
    log::Logger::ptr async_logger  = builder->build();
    // std::cout << async_logger->get_loggerName();

    // for(int i=0;i<50000;i++)
    // {
    //     async_logger->debug(__FILE__,__LINE__,"%s-%d","测试信息",i+1);
    // }
    test_log();
    //DEBUG("%s","业务结束");  
    //test_6();
    return 0;
}